package middleware

import (
	"context"
	"net/http"
	"walnut/kernel"

	"github.com/golang-jwt/jwt/v5"
)

func Auth(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// 从请求头中获取 JWT 令牌
		tokenString := r.Header.Get(kernel.Conf.JWT.KeyName)
		if tokenString == "" {
			cookie, err := r.Cookie(kernel.Conf.JWT.KeyName)
			if err != nil {
				if err == http.ErrNoCookie {
					w.WriteHeader(http.StatusUnauthorized)
					kernel.Failure(w, http.StatusUnauthorized, "未找到登陆凭证")
					return
				}
				w.WriteHeader(http.StatusUnauthorized)
				kernel.Failure(w, http.StatusUnauthorized, "获取供登陆凭证失败")
				return
			}
			tokenString = cookie.Value
		}
		claims := kernel.Claims{}
		token, err := jwt.ParseWithClaims(tokenString, &claims, func(token *jwt.Token) (interface{}, error) {
			return []byte(kernel.Conf.JWT.SecretKey), nil
		})
		if err != nil {
			if err == jwt.ErrSignatureInvalid {
				w.WriteHeader(http.StatusUnauthorized)
				kernel.Failure(w, http.StatusUnauthorized, "登陆凭证签名无效")
				return
			}
			w.WriteHeader(http.StatusUnauthorized)
			kernel.Failure(w, http.StatusUnauthorized, "登陆凭证解析错误")
			return
		}
		if !token.Valid {
			w.WriteHeader(http.StatusUnauthorized)
			kernel.Failure(w, http.StatusUnauthorized, "登陆凭证已失效")
			return
		}

		var ck kernel.CtxKey = "claims"
		// 将用户名添加到请求的上下文，以便后续处理函数使用
		r = r.WithContext(context.WithValue(r.Context(), ck, claims))
		next.ServeHTTP(w, r)
	}
}
